package com.ndood.core.render.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.openqa.selenium.Dimension;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy.ProxyType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ndood.core.proxy.DynamicIpPortGenerator;
import com.ndood.core.proxy.UserAgentGenerator;
import com.ndood.core.render.SeleniumDriverPool;
import com.ndood.core.util.PropertiesUtil;

/**
 * Chrome WebDriver队列（池）
 */
public class ChromeDriverPool implements SeleniumDriverPool {
	private Logger logger = LoggerFactory.getLogger(getClass());

	/**
	 * 最大webDriver数量
	 */
	private int CAPACITY = 30;

	/**
	 * 当前webDriver数量
	 */
	private AtomicInteger refCount = new AtomicInteger(0);

	/**
	 * 内存阻塞队列
	 */
	private BlockingDeque<WebDriver> driverQueue = new LinkedBlockingDeque<WebDriver>(CAPACITY);

	public ChromeDriverPool() {
		super();
	}

	public ChromeDriverPool(int poolsize) {
		this.CAPACITY = poolsize;
		driverQueue = new LinkedBlockingDeque<WebDriver>(poolsize);
	}

	/**
	 * 从队列中取出一个webDriver
	 */
	public WebDriver get() throws InterruptedException {
		// Step1: 如果webDriver数量已最大，则从队列中取
		if (refCount.get() >= CAPACITY) {
			return driverQueue.take();
		}

		// Step2: 初始化谷歌浏览器属性
		System.getProperties().setProperty("webdriver.chrome.driver",
				PropertiesUtil.readProperty("chrome.driver.path"));
		DesiredCapabilities caps = DesiredCapabilities.chrome();
		ChromeOptions options = new ChromeOptions();
		// options.addExtensions(new File("/path/to/extension.crx")) 证书
		// options.setBinary(PropertiesUtil.readProperty("chrome.path"));
		// //注意chrome和chromeDirver的区别，默认浏览器不用设
		options.addArguments("test-type"); // ignore certificate errors
		options.addArguments("headless");// headless mode
		options.addArguments("disable-gpu");
		// options.addArguments("log-path=chromedriver.log");
		// options.addArguments("screenshot"); 每打开一个页面就截图
		// options.addArguments("start-maximized"); 最大化
		// options.addArguments("user-agent=" + UserAgentGenerator.generate());
		
		// 模拟手机浏览器方式1
		// options.addArguments("user-agent=" + UserAgentGenerator.generateMobile()); // 随机的user-agent
		// 模拟手机浏览器方式2
		/*Map<String, String> mobileEmulation = new HashMap<String, String>(); 
		mobileEmulation.put("deviceName", "iPhone 6"); // Google Nexus 7/Apple iPhone 6
		options.setExperimentalOption("mobileEmulation", mobileEmulation);*/

		Map<String, Object> prefs = new HashMap<String, Object>();
		// prefs.put("profile.default_content_settings.popups", 0);
		// http://stackoverflow.com/questions/28070315/python-disable-images-in-selenium-google-chromedriver
		prefs.put("profile.managed_default_content_settings.images", 2); // 禁止下载加载图片
		options.setExperimentalOption("prefs", prefs);
		caps.setJavascriptEnabled(true);
		caps.setCapability(ChromeOptions.CAPABILITY, options);
		// caps.setCapability("takesScreenshot", false);

		// Step3: 配置代理
		/*String ipAndPort = DynamicIpPortGenerator.generate();
		Proxy proxy = new Proxy();
		proxy.setHttpProxy(ipAndPort).setFtpProxy(ipAndPort).setSslProxy(ipAndPort).setNoProxy("None").setProxyType(ProxyType.MANUAL).setAutodetect(false);
		caps.setCapability(CapabilityType.ForSeleniumServer.AVOIDING_PROXY, true);
		caps.setCapability(CapabilityType.ForSeleniumServer.ONLY_PROXYING_SELENIUM_TRAFFIC, true);
		System.setProperty("http.nonProxyHosts", "localhost");
		caps.setCapability("proxy", proxy);*/

		// Step4: 如果webDriver数量未达到最大，则新增一个
		WebDriver webDriver = new ChromeDriver(caps);
		webDriver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
		webDriver.manage().window().setSize(new Dimension(1366, 768));
		refCount.incrementAndGet();
		driverQueue.put(webDriver);

		// Step5: 先放入队列中然后再取
		webDriver = driverQueue.take();
		return webDriver;
	}

	/**
	 * 用完之后返回一个webDriver到队列中
	 */
	public void returnToPool(WebDriver webDriver) {
		try {
			driverQueue.put(webDriver);
		} catch (InterruptedException e) {
			logger.warn("returnToPool InterruptedException", e);
		}
	}

	/**
	 * 关闭webDriver队列
	 */
	public void shutdown() {
		try {
			for (WebDriver driver : driverQueue) {
				refCount.decrementAndGet();
				driver.close();
				driver.quit();
				driver = null;
			}
			driverQueue.clear();
		} catch (Exception e) {
			logger.warn("webdriverpool关闭失败", e);
		}
	}
}
